from django.db import transaction
from django.utils import timezone
from rest_framework import serializers
from .models import Exam, ExamDepart
from apps.PaperManagement.serializers import PaperSerializer
from ..DepartManagement.models import Department
from ..UserManagement.models import User


class ExamSerializer(serializers.ModelSerializer):
    # 允许重做字段
    re_answer = serializers.IntegerField(default=0)
    show_answer = serializers.IntegerField(default=0)
    paper_id = serializers.CharField(source='paper.id', read_only=True)
    parent = serializers.CharField(source='parent.id', read_only=True)
    # 获取关联的部门列表
    departments = serializers.SerializerMethodField()
    users = serializers.SerializerMethodField()
    children = serializers.SerializerMethodField()

    class Meta:
        model = Exam
        fields = "__all__"

    def to_representation(self, instance):
        """转换布尔值为 0 和 1"""
        representation = super().to_representation(instance)
        representation['re_answer'] = 1 if instance.re_answer else 0
        representation['show_answer'] = 1 if instance.show_answer else 0

        # 在序列化之后给每个子考试添加排序字段
        if 'children' in representation:
            for idx, child in enumerate(representation['children']):
                child['order'] = f"{idx + 1}"
        return representation

    def to_internal_value(self, data):
        """转换 0 和 1 为布尔值"""
        if 're_answer' in data:
            data['re_answer'] = True if data['re_answer'] == 1 else False
        if 'show_answer' in data:
            data['show_answer'] = True if data['show_answer'] == 1 else False
        return super().to_internal_value(data)

    def get_departments(self, obj):
        """返回与该考试关联的所有部门，包括id和name"""
        # 获取所有与该考试相关的部门
        exam_departments = ExamDepart.objects.filter(exam=obj)
        departments = [
            {"id": department.depart.id, "name": department.depart.name}
            for department in exam_departments if department.depart
        ]
        return departments

    def get_users(self, obj):
        """返回与该考试关联的所有用户"""
        exam_departments = ExamDepart.objects.filter(exam=obj)
        users = [
            {
                "id": department.user.id,
                "username": department.user.username,
                "name": department.user.name,
                "department": department.user.depart.name if department.user.depart else None  # 获取用户的部门名称
            }
            for department in exam_departments if department.user
        ]
        return users

    def get_children(self, obj):
        children = Exam.objects.filter(parent=obj).order_by('created_at')
        serializer = ExamListSerializer(children, many=True)
        return serializer.data


class ExamListSerializer(serializers.ModelSerializer):
    re_answer = serializers.IntegerField(default=0)
    show_answer = serializers.IntegerField(default=0)
    paper_id = serializers.CharField(source='paper.id', read_only=True)
    paper_name = serializers.CharField(source='paper.exam_name', read_only=True)
    parent = serializers.CharField(source='parent.id', read_only=True)
    countdown = serializers.CharField(read_only=True)
    # 获取关联的部门列表
    departments = serializers.SerializerMethodField()
    users = serializers.SerializerMethodField()
    children = serializers.SerializerMethodField()

    class Meta:
        model = Exam
        fields = ['id', 'title', 'start_time', 'end_time', 'status', 'number', 're_answer', "paper_id", 'paper_name',
                  'departments', 'users', 'show_answer', 'parent', 'countdown', 'children']

    def to_representation(self, instance):
        """转换布尔值为 0 和 1"""
        representation = super().to_representation(instance)
        representation['re_answer'] = 1 if instance.re_answer else 0
        representation['show_answer'] = 1 if instance.show_answer else 0

        # 如果有父考试，处理父考试的顺序，并给子考试添加 order
        if instance.parent:
            parent_exam = instance.parent  # 父考试
            children_exams = Exam.objects.filter(parent=parent_exam).order_by('created_at')

            # 给每个子考试添加 order 字段
            for idx, child_exam in enumerate(children_exams):
                if child_exam.id == instance.id:
                    representation['order'] = f"{idx + 1}"

        return representation

    def to_internal_value(self, data):
        """转换 0 和 1 为布尔值"""
        if 're_answer' in data:
            data['re_answer'] = True if data['re_answer'] == 1 else False
        if 'show_answer' in data:
            data['show_answer'] = True if data['show_answer'] == 1 else False
        return super().to_internal_value(data)

    def get_departments(self, obj):
        """返回与该考试关联的所有部门，包括id和name"""
        # 获取所有与该考试相关的部门
        exam_departments = ExamDepart.objects.filter(exam=obj)
        departments = [
            {"id": department.depart.id, "name": department.depart.name}
            for department in exam_departments if department.depart
        ]
        return departments

    def get_users(self, obj):
        """返回与该考试关联的所有用户"""
        exam_departments = ExamDepart.objects.filter(exam=obj)
        users = [
            {
                "id": department.user.id,
                "username": department.user.username,
                "name": department.user.name,
                "department": department.user.depart.name if department.user.depart else None  # 获取用户的部门名称
            }
            for department in exam_departments if department.user
        ]
        return users

    def get_children(self, obj):
        children = Exam.objects.filter(parent=obj).order_by('created_at')
        if not children:
            return []
        serializer = ExamListSerializer(children, many=True)
        return serializer.data

    def validate_time(self, instance):
        if instance.start_time >= instance.end_time:
            raise serializers.ValidationError("考试结束时间必须晚于开始时间")

        current_time = timezone.now()

        if instance.end_time < current_time and instance.status != 2:
            instance.status = 3

        elif instance.start_time <= current_time < instance.end_time and instance.status != 1:
            instance.status = 1

        instance.save()

    def validate_paper(self, instance):
        if not instance.paper:
            instance.status = 3
            instance.save()
            return False
        return True

    def validate_associations(self, instance):
        exam_departments = ExamDepart.objects.filter(exam=instance)

        if not exam_departments:
            instance.status = 3
            instance.save()
            return False

        for department in exam_departments:
            if department.depart.id:
                depart = Department.objects.filter(id=department.depart.id).first()
                if not depart:
                    instance.status = 3
                    instance.save()
                    return False
            if department.user.id:
                user = User.objects.filter(id=department.user.id).first()
                if not user:
                    instance.status = 3
                    instance.save()
                    return False

        return True

    @transaction.atomic
    def save(self, *args, **kwargs):
        try:
            self.validate_time(self.instance)
            if not self.validate_paper(self.instance):
                return
            if not self.validate_associations(self.instance):
                return

            super().save(*args, **kwargs)
        except Exception as e:
            self.instance.status = 3
            self.instance.save()  # 确保状态更新保存到数据库
            raise e  # 抛出异常以便外部处理


class UnExamUserSerializer(serializers.Serializer):
    username = serializers.CharField(read_only=True)
    name = serializers.CharField(read_only=True)
    status = serializers.CharField(read_only=True)
    start_time = serializers.DateTimeField(read_only=True)
    created_time = serializers.DateTimeField(read_only=True)
    response_rate = serializers.IntegerField(read_only=True)
